//#pragma optimize(off)
#define MAX_RES 8
#define MAX_COLOR_SIZE (MAX_RES+2)*(MAX_RES+1)/2

uniform vec4 color[MAX_COLOR_SIZE];
uniform int res ;
uniform float k ;


/*Texture coordinates of triangle are
(0,0),(1,0) and (k,1)*/
void transform (in float k, in vec2 st, out vec2 p[3], out int idx [3])
{
	float t = st.t;
	float s = st.s;
	
	s = s - k * t; /*Skew Transformation*/
	

	float offset = 1.0 / float (res);
	int x_idx = int (s / offset) ;
	int y_idx = int (t / offset);
	
	int total = (res + 1) * (res + 2) / 2;
	int clr_idx = total - (res - y_idx + 1) * (res-y_idx + 2) / 2;
	
    if (s + t < float (x_idx + y_idx + 1) * offset)
    {
		idx[0] = clr_idx + x_idx + res + 1 - y_idx;
		idx[1] = clr_idx + x_idx + 1;
		idx[2] = clr_idx + x_idx ; 
			
		p[0] = vec2( float(x_idx) * offset, float(y_idx + 1) * offset);
		p[1] = vec2(float(x_idx + 1) * offset,float( y_idx) * offset);
		p[2] = vec2(float(x_idx)  * offset, float(y_idx) * offset);
    }
    else
    {
		idx[0] = clr_idx + x_idx + 1;
		idx[1] = clr_idx + x_idx + res +1 - y_idx ;
		idx[2] = idx[1] + 1;

        p[0] = vec2(float(x_idx+1) * offset, float(y_idx ) * offset);
        p[1] = vec2(float(x_idx ) * offset, float(y_idx+1) * offset);
        p[2] = vec2(float(x_idx +1) * offset,float(y_idx+1) * offset);
    }
	
	p[0].x = p[0].x + k * p[0].y; 
	p[1].x = p[1].x + k * p[1].y;
	p[2].x = p[2].x + k * p[2].y;
}

vec4 nearest (in vec2 st, in vec2 p[3], in int idx [3])
{
	vec4 c ;
	float dis1, dis2, dis3;
	dis1 = distance (st, p[0]);
	dis2 = distance (st, p[1]);
	dis3 = distance (st, p[2]);

	if (dis1 < dis2 && 
	   dis1 < dis3)
	{
		c = color[idx[0]];
	}
	else if (dis2 < dis1 && 
	   dis2 < dis3)
	{
		c = color[idx[1]];
	}
	else
	{
		c = color[idx[2]];
	}
	return c;
}

float det3 (in mat3 m)
{
	float det = m[0][0] *(m[2][2]*m[1][1] - m[2][1]* m[1][2]) 
			- m[1][0] * (m[2][2]*m[0][1] - m[2][1]* m[0][2])
			+ m[2][0] * (m[1][2]*m[0][1] - m[1][1]* m[0][2]);
	return det ;
}
mat3 inverse3 (in mat3 m)
{
	float rdet = 1.0 / det3(m);
	mat3 invm ;
	invm[0][0] =   rdet * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) ;
	invm[0][1] = - rdet * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) ;
	invm[0][2] =   rdet * (m[0][1] * m[1][2] - m[0][2] * m[1][1]) ;

	invm[1][0] = - rdet * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) ;
	invm[1][1] =   rdet * (m[0][0] * m[2][2] - m[0][2] * m[2][0]) ;
	invm[1][2] = - rdet * (m[0][0] * m[1][2] - m[0][2] * m[1][0]) ;

	invm[2][0] =   rdet * (m[1][0] * m[2][1] - m[1][1] * m[2][0]) ;
	invm[2][1] = - rdet * (m[0][0] * m[2][1] - m[0][1] * m[2][0]) ;
	invm[2][2] =   rdet * (m[0][0] * m[1][1] - m[0][1] * m[1][0]) ;
	return invm;
}

vec4 linear (in vec2 st, in vec2 p[3], in int idx [3])
{
	mat3 m =  mat3(p[0].x , p[0].y, 1.0, p[1].x, p[1].y, 1.0, p[2].x, p[2].y, 1.0) ;

	mat3 invm = inverse3(m);
	vec3 bc = invm * vec3(st.s, st.t, 1);
	vec4 c = color[idx[0]] * bc.x + color[idx[1]] * bc.y + color[idx[2]] * bc.z;
	return c;
}

void main()
{
	vec2 p[3]; 
	int idx[3];
	vec2 st = gl_TexCoord[0].st;
	transform(k, st, p, idx);
	gl_FragColor = nearest(st, p,idx);
	//gl_FragColor = linear(st, p,idx);
}
